package com.fashion.server.common;

import com.fashion.server.common.IConstants.ParamDefine.CrudEnum;
import com.fashion.server.common.IConstants.ParamDefine.OperatorType;
import com.fashion.server.common.IConstants.ParamDefine.OrderDirection;
import com.fashion.server.common.IConstants.ParamDefine.QueryFields;
import com.fashion.server.common.IConstants.ResponseDefine.Code;
import com.fashion.server.domain.model.BaseModel;
import com.fashion.server.domain.request.QueryCondition;
import com.fashion.server.domain.response.ResponseData;
import com.fashion.server.utils.ConfigUtil;
import com.fashion.server.utils.StringUtil;
import org.springframework.dao.DataAccessException;

import java.sql.SQLException;
import java.util.*;


/**
 * controller基类
 * @author WangXin
 *
 */
public abstract class BaseController {
	
	// 基本展示字段
	protected Map<String, String> BASE_FIELDS = new HashMap<String, String>();
	
	private final static String MSG_IS_MUST = "参数错误:缺少%1$s字段";
	private final static String MSG_IS_NOEXIST = "参数错误:%1$s字段中包含不存在的属性%2$s";
	private final static String MSG_IS_ONLY = "参数错误:%1$s字段中只能包含%2$s属性";

	protected final static Integer SUCCESS = Code.SUCCESS_200.getIndex();
	protected final static Integer PARAM_ECODE = Code.ERROR_402.getIndex();
	
	public BaseController(){
		initBaseFields();
	}

	protected abstract void initBaseFields();


	/**
	 * 检查添增删改查参数
	 * 
	 * @param
	 * @param object
	 * @return
	 */
	protected ResponseData checkCRUDParam(CrudEnum crudEnum,
										  Object object) {
		BaseModel baseModel;
		switch (crudEnum) {
			case QUERY :
				baseModel = (BaseModel) object;
				return checkAllQueryParam(baseModel);
			case ADD :
			case DELETE :
			case MODIFY :
			default :
				baseModel = (BaseModel) object;
				return checkAllQueryParam(baseModel);
		}
	}
	
	/**
	 * 检查fields字段
	 * 
	 * @param fields
	 * @return
	 */
	protected ResponseData checkQueryFields(String fields,
			String fieldName) {
		// 检查fields字段
		if (StringUtil.isBlank(fields)) {
			return new ResponseData(PARAM_ECODE,
					String.format(MSG_IS_MUST, fieldName));
		}

		String[] fieldsArray = fields.split(",");
		for (int i = 0; i < fieldsArray.length; i++) {
			String f = fieldsArray[i].trim();
			if (!BASE_FIELDS.containsKey(f)) {
				return new ResponseData(PARAM_ECODE,
						String.format(MSG_IS_NOEXIST, fieldName, f));
			}
		}

		return new ResponseData(SUCCESS);
	}
	
	/**
	 * 检查查询参数
	 * 
	 * @param model
	 * @return
	 */
	private ResponseData checkAllQueryParam(BaseModel model) {

		String fields = model.getFields();
		String orderColumn = model.getOrderColumn();
		Integer orderDirection = model.getOrderDirection();

		ResponseData responseData = null;
		// size字段检测
		responseData = this.checkSize(model);
		if (responseData.getCode() != SUCCESS) {
			return responseData;
		}

		// fields字段检测
		responseData = this.checkQueryFields(fields, QueryFields.FIELDS);
		if (responseData.getCode() != SUCCESS) {
			return responseData;
		}

		// 转换fields 为 db fields
		model.setFields(transProperties2DbFields(fields, BASE_FIELDS));

		// 检查orderDirection
		if (orderDirection != null) {
			List<Integer> keySet = OrderDirection.ValueList();
			if (!keySet.contains(orderDirection)) {
				return new ResponseData(PARAM_ECODE, String.format(MSG_IS_ONLY,
						QueryFields.ORDERDRECTION, keySet.toString()));
			}

			if (StringUtil.isBlank(orderColumn)) {
				return new ResponseData(PARAM_ECODE,
						String.format(MSG_IS_MUST, QueryFields.ORDERCOLUMN));
			}
		}

		// 检查orderColumn
		StringBuffer newOrderColumn = new StringBuffer();
		if (!StringUtil.isBlank(orderColumn)) {
			String[] array = orderColumn.split(",");
			for (int i = 0; i < array.length; i++) {
				String f = array[i].trim();
				if (!BASE_FIELDS.containsKey(f)) {
					return new ResponseData(PARAM_ECODE, String.format(MSG_IS_ONLY,
							QueryFields.ORDERCOLUMN, f));
				}
				if(f.contains("_Count")){
					newOrderColumn.append(f).append(",");
				}else{
					newOrderColumn.append(BASE_FIELDS.get(f)).append(",");
				}
			}
			newOrderColumn.deleteCharAt(newOrderColumn.length() - 1);
			model.setOrderColumn(newOrderColumn.toString());

		}else if(null != orderColumn){
			return new ResponseData(PARAM_ECODE,
					String.format(MSG_IS_MUST, QueryFields.ORDERCOLUMN));
		}

		// 检查queryConditions的内容
		responseData = checkQueryConditions(model.getQueryConditions());
		if (responseData.getCode() != SUCCESS) {
			return responseData;
		}

		return new ResponseData(SUCCESS);
	}
	
	/**
	 * 转换属性为数据库对应的字段
	 * 
	 * @param fields
	 *            如 brandId,brandName
	 * @return brand_id,brand_name
	 */
	protected String transProperties2DbFields(String fields,
			Map<String, String> fieldsMap) {
		if (StringUtil.isBlank(fields)) {
			return "";
		}
		String[] fieldsArray = fields.split(",");

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < fieldsArray.length; i++) {
			String field = fieldsArray[i].trim();
			if (fieldsMap.containsKey(field)) {
				sb.append(fieldsMap.get(field)).append(",");
			}
		}
		sb.deleteCharAt(sb.length() - 1);
		return sb.toString();
	}
	
	/**
	 * 检查size
	 * 
	 * @param model
	 * @return
	 */
	private ResponseData checkSize(BaseModel model) {
		Integer size = model.getSize();
		Integer start = model.getStart();
		// size校验，
		String max_size = ConfigUtil.getString("max_page_size");
		if(StringUtil.isBlank(max_size)){
			max_size="100";
		}
		if (size != null && size > Integer.valueOf(max_size)) {
			return new ResponseData(PARAM_ECODE, "参数错误:size参数不能大于" + max_size);
		}else if(size != null && size<0){
			return new ResponseData(PARAM_ECODE, "参数错误:size参数不能小于0");
		}else if(start != null && start<0){
			return new ResponseData(PARAM_ECODE, "参数错误:start参数不能小于0");
		}
		if (size == null) {
			model.setSize(Integer.valueOf(max_size));
		}
		return new ResponseData(SUCCESS);
	}
	
	/**
	 * 检查queryCondition的值
	 * 
	 * @param queryConditions
	 * @return
	 */
	private ResponseData checkQueryConditions(
			List<QueryCondition> queryConditions) {

		if (queryConditions == null || queryConditions.size() == 0) {
			return new ResponseData();
		}

		for (QueryCondition queryCondition : queryConditions) {

			String columnName = queryCondition.getColumnName();
			Object columnValue = queryCondition.getColumnValue();
			Integer type = queryCondition.getType();

			// 检查columnName字段
			if (StringUtil.isBlank(columnName)) {
				return new ResponseData(PARAM_ECODE,
						String.format(MSG_IS_MUST, QueryFields.COLUMNNAME));
			}
			if (!BASE_FIELDS.containsKey(columnName)) {
				return new ResponseData(PARAM_ECODE, String.format(MSG_IS_NOEXIST,
						QueryFields.COLUMNNAME, columnName));
			}
			queryCondition.setColumnName(BASE_FIELDS.get(columnName.trim()));

			// 检查type字段
			if (type == null) {
				return new ResponseData(PARAM_ECODE,
						String.format(MSG_IS_MUST, QueryFields.TYPE));
			}
			List<Integer> typeList = OperatorType.keyList();
			if (!typeList.contains(type)) {
				return new ResponseData(PARAM_ECODE,
						String.format(MSG_IS_ONLY, QueryFields.TYPE, typeList));
			}

			// 检查columnValue字段
			if (null == columnValue) {
				return new ResponseData(PARAM_ECODE,
						String.format(MSG_IS_MUST, QueryFields.COLUMNVALUE));
			}
		}
		return new ResponseData(SUCCESS, Code.SUCCESS_200.getValue());
	}
	
	protected int getSqlErrorCode(DataAccessException e){
		int code = Code.ERROR_505.getIndex();
		try {
			if(e.getCause() instanceof SQLException) {
				SQLException sqlException = (SQLException)e.getCause();
				switch (sqlException.getErrorCode()) {
				case 1062:
					code = Code.ERROR_506.getIndex();
					break;
				default:
					break;
				};
			}
		} catch (Exception e1) {
		}
		return code;
	}

	/**
	 * 请求参数拼接
	 * @param sortedParams
	 * @return
	 */
	protected String getSignContent(Map<String, Object> sortedParams) {
		StringBuffer content = new StringBuffer();
		List<String> keys = new ArrayList<String>(sortedParams.keySet());
		Collections.sort(keys);
		int index = 0;
		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = sortedParams.get(key).toString();
			if (StringUtil.areNotEmpty(key, value)) {
				content.append((index == 0 ? "" : "&") + key + "=" + value);
				index++;
			}
		}
		return content.toString();
	}
}
